#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include "../lib_include/TimerQueue.h"
#include "../lib_include/Logger.h"
#include "../lib_include/EventLoop.h"
#include "../lib_include/Timer.h"
#include "../lib_include/TimerId.h"

#include <sys/timerfd.h>
#include <unistd.h>

namespace netlib
{

namespace net
{

namespace detail
{

int createTimerfd() // 创建一个定时器
{
    // 系统调用创建定时器fd
    int timerfd = ::timerfd_create(CLOCK_MONOTONIC,
                                    TFD_NONBLOCK | TFD_CLOEXEC);
    if (timerfd < 0)
        LOG_SYSFATAL << "Failed in timerfd_create";
    return timerfd;
}

struct timespec howMuchTimeFromNow(Timestamp when) // 返回已经过去了多少秒
{
    int64_t microseconds = when.microSecondsSinceEpoch()
                            - Timestamp::now().microSecondsSinceEpoch();
    if (microseconds < 100)
        microseconds = 100;
    struct timespec ts;
    ts.tv_sec = static_cast<time_t>(
        microseconds / Timestamp::kMicroSecondsPerSecond);
    ts.tv_nsec = static_cast<long>(
        (microseconds % Timestamp::kMicroSecondsPerSecond) * 1000);
    return ts;
}

void readTimerfd(int timerfd, Timestamp now) // 读取定时器fd上的数据，防止多次触发poll
{
    uint64_t howmany;

    // 将定时器fd的数据读取完，保证定时信号只触发一次
    ssize_t n = ::read(timerfd, &howmany, sizeof howmany);
    LOG_TRACE << "TimerQueue::handleRead() " << howmany << " at " << now.toString();
    if (n != sizeof howmany)
        LOG_ERROR << "TimerQueue::handleRead() reads " << n << " bytes instead of 8";
}

void resetTimerfd(int timerfd, Timestamp expiration) // 重新设置定时器超时时间
{
    struct itimerspec newValue;
    struct itimerspec oldValue;
    memZero(&newValue, sizeof newValue);
    memZero(&oldValue, sizeof oldValue);
    newValue.it_value = howMuchTimeFromNow(expiration);
    int ret = ::timerfd_settime(timerfd, 0, &newValue, &oldValue);
    if (ret)
        LOG_SYSERR << "timerfd_settime()";
}

} // namespace detail end

} // namespace net end

} // namespace netlib end

using namespace netlib;
using namespace netlib::net;
using namespace netlib::net::detail;

TimerQueue::TimerQueue(EventLoop* loop)
  : loop_(loop),
    timerfd_(createTimerfd()),
    timerfdChannel_(loop, timerfd_),
    timers_(),
    callingExpiredTimers_(false)
{
    timerfdChannel_.setReadCallback(std::bind(&TimerQueue::handleRead, this));
    timerfdChannel_.enableReading();
}

TimerQueue::~TimerQueue()
{
    timerfdChannel_.disableAll();
    timerfdChannel_.remove();
    ::close(timerfd_);
    for (const Entry& timer : timers_)
        delete timer.second;
}

// 添加一个定时器，addTimerInLoop的封装
TimerId TimerQueue::addTimer(TimerCallback cb, Timestamp when, double interval)
{
    Timer* timer = new Timer(std::move(cb), when, interval);
    loop_->runInLoop(std::bind(&TimerQueue::addTimerInLoop, this, timer));
    return TimerId(timer, timer->sequence());
}

 // 关闭定时器，cancelInLoop的封装
void TimerQueue::cancel(TimerId timerId)
{ loop_->runInLoop(std::bind(&TimerQueue::cancelInLoop, this, timerId)); }

// 添加一个定时器
void TimerQueue::addTimerInLoop(Timer* timer)
{
    loop_->assertInLoopThread(); // 断言调用者线程
    bool earliestChanged = insert(timer); // 判断新插入的定时器是否为最早到期

    if (earliestChanged)
        resetTimerfd(timerfd_, timer->expiration());
}

// 关闭定时器
void TimerQueue::cancelInLoop(TimerId timerId)
{
    loop_->assertInLoopThread(); // 断言创建者线程
    assert(timers_.size() == activeTimers_.size());
    ActiveTimer timer(timerId.timer_, timerId.sequence_);
    ActiveTimerSet::iterator it = activeTimers_.find(timer);
    if (it != activeTimers_.end()) // 找到该定时器
    {
        size_t n = timers_.erase(Entry(it->first->expiration(), it->first));
        assert(n == 1); (void)n;
        delete it->first;
        activeTimers_.erase(it);
    }
    else if (callingExpiredTimers_) // 如果该定时器任务正在执行，则将其插入销毁列表中
        cancelingTimers_.insert(timer);
    assert(timers_.size() == activeTimers_.size());
}

void TimerQueue::handleRead() // 处理超时定时器
{
    loop_->assertInLoopThread(); // 断言创建者线程
    Timestamp now(Timestamp::now());
    readTimerfd(timerfd_, now);

    std::vector<Entry> expired = getExpired(now); // 获得超时定时器

    callingExpiredTimers_ = true; // 设置正在处理超时定时器状态
    cancelingTimers_.clear();
    for (const Entry& it : expired)
        it.second->run();
    callingExpiredTimers_ = false;

    reset(expired, now); // 根据定时器属性进行重置
}

// 返回超时的定时器列表
std::vector<TimerQueue::Entry> TimerQueue::getExpired(Timestamp now)
{
    assert(timers_.size() == activeTimers_.size());
    std::vector<Entry> expired; // 用来存储超时的定时器
    Entry sentry(now, reinterpret_cast<Timer*>(UINTPTR_MAX));

    // lower_bound(value)，返回第一个大于等于value的迭代器
    // 在列表中查找第一个不超时的定时器end
    TimerList::iterator end = timers_.lower_bound(sentry);
    assert(end == timers_.end() || now < end->first);

    // 从 [begin,end) 即已经超时的定时器，取出到expired，并在列表中删除
    std::copy(timers_.begin(), end, back_inserter(expired));
    timers_.erase(timers_.begin(), end);

    for (const Entry& it : expired)
    {
        ActiveTimer timer(it.second, it.second->sequence());
        size_t n = activeTimers_.erase(timer);
        assert(n == 1); (void)n;
    }

    assert(timers_.size() == activeTimers_.size());
    return expired;
}

// 对超时的定时器进行重置
void TimerQueue::reset(const std::vector<Entry>& expired, Timestamp now)
{
    Timestamp nextExpire;

    for (const Entry& it : expired)
    {
        ActiveTimer timer(it.second, it.second->sequence());
        if (it.second->repeat() // 判断定时器是否开启重复
            && cancelingTimers_.find(timer) == cancelingTimers_.end()) // 且不在销毁列表
        {
            it.second->restart(now);
            insert(it.second);
        }
        else // 否则就删除定时器
            delete it.second;
    }

    if (!timers_.empty()) // 列表中还有定时任务
        nextExpire = timers_.begin()->second->expiration(); // 获得最近的超时时间

    if (nextExpire.valid()) // 超时时间存在
        resetTimerfd(timerfd_, nextExpire); // 将最近的超时时间注册到定时器fd
}

bool TimerQueue::insert(Timer* timer) // 插入一个定时器
{
    loop_->assertInLoopThread(); // 断言创建者线程
    assert(timers_.size() == activeTimers_.size());
    bool earliestChanged = false;
    Timestamp when = timer->expiration();
    TimerList::iterator it = timers_.begin(); // 得到列表中第一个定时器
    if (it == timers_.end() || when < it->first)
        earliestChanged = true; // 新插入的是最早到期的定时器
    {
        std::pair<TimerList::iterator, bool> result
        = timers_.insert(Entry(when, timer));
        assert(result.second); (void)result;
    }
    {
        std::pair<ActiveTimerSet::iterator, bool> result
        = activeTimers_.insert(ActiveTimer(timer, timer->sequence()));
        assert(result.second); (void)result;
    }

    assert(timers_.size() == activeTimers_.size());
    return earliestChanged;
}
